#include "client.h"

typedef struct {
    tlvPacket_t tlv;
    char username[4096];
    char cHead[4096];
    char token[41];
    char ip[1024];
    char port[1024];
} element_t;

// signal专用
int reSockfd;
element_t signalElement;


void handler(int sig){
    close(reSockfd);
    // 新建TCP连接
    reSockfd = tcpInit(signalElement.ip, signalElement.port);                                             
    tlvPacket_t tlv;
    memset(&tlv, 0, sizeof(tlv));

    // 判断token                                                
    int tokenExist = (strlen(signalElement.token) == 0) ? -1 : 1;             
    send(reSockfd, &tokenExist, sizeof(tokenExist), MSG_NOSIGNAL);
    if(tokenExist == 1){
        // 发送用户名
        tlv.type = signalElement.tlv.type;
        tlv.length = strlen(signalElement.username);
        memcpy(tlv.value, signalElement.username, tlv.length);
        send(reSockfd, &tlv, sizeof(tlv.type)+sizeof(tlv.length)+
             tlv.length, MSG_NOSIGNAL);

        // 发送token
        send(reSockfd, signalElement.token, sizeof(signalElement.token), MSG_NOSIGNAL);

        // 接收标志
        int tag;
        recv(reSockfd, &tag, sizeof(int), MSG_WAITALL);
        if(tag == 1){

            // 重新发送命令和参数
            memcpy(&tlv, &signalElement.tlv, sizeof(tlv));
            send(reSockfd, &tlv, sizeof(tlv.type)+sizeof(tlv.length)+
                 tlv.length, MSG_NOSIGNAL);

        }
        else{
            printf("token验证失败！\n");
            exit(-1);
        }
    }
}

static void *threadFunc(void *arg){
    element_t *element  = (element_t *)arg;
    int sockfd = tcpInit(element->ip, element->port);
    tlvPacket_t tlv;
    memset(&tlv, 0, sizeof(tlv));
    // 判断token                                                
    int tokenExist = (strlen(element->token) == 0) ? -1 : 1;             
    send(sockfd, &tokenExist, sizeof(tokenExist), MSG_NOSIGNAL);
    if(tokenExist == 1){
        // 发送用户名
        tlv.type = element->tlv.type;
        tlv.length = strlen(element->username);
        memcpy(tlv.value, element->username, tlv.length);
        send(sockfd, &tlv, sizeof(tlv.type)+sizeof(tlv.length)+
             tlv.length, MSG_NOSIGNAL);

        // 发送token
        send(sockfd, element->token, sizeof(element->token), MSG_NOSIGNAL);

        // 接收标志
        int tag;
        recv(sockfd, &tag, sizeof(int), MSG_WAITALL);
        if(tag == 1){

            // 发送命令和参数
            memcpy(&tlv, &element->tlv, sizeof(tlv));
            send(sockfd, &tlv, sizeof(tlv.type)+sizeof(tlv.length)+
                 tlv.length, MSG_NOSIGNAL);

            // 发送用户名
            tlv.length = strlen(element->username);
            memcpy(tlv.value, element->username, tlv.length);
            send(sockfd, &tlv, sizeof(tlv.type)+sizeof(tlv.length)+
                 tlv.length, MSG_NOSIGNAL);

            // 发送cHead
            tlv.length = strlen(element->cHead);
            memcpy(tlv.value, element->cHead, tlv.length);
            send(sockfd, &tlv, sizeof(tlv.type)+sizeof(tlv.length)+
                 tlv.length, MSG_NOSIGNAL);

            // 发送token
            send(sockfd, element->token, sizeof(element->token), MSG_NOSIGNAL);

            // 文件上传
            if(tlv.type == PUTS){
                puts_client(sockfd, element->tlv.value);

                // 接受标志
                int mark = 0;
                recv(sockfd, &mark, sizeof(int), MSG_WAITALL);
                if(mark == -1){
                    printf("puts false!\n");
                }
            }

            // 文件下载
            if(tlv.type == GETS){
                gets_client(sockfd, element->tlv.value);

                // 接受标志
                int mark = 0;
                recv(sockfd, &mark, sizeof(int), MSG_WAITALL);
                if(mark == -1){
                    printf("gets false!\n");
                }
            }
        }
        else{
            close(sockfd);
            pthread_exit(NULL);
        }
    }
    close(sockfd);
    return NULL;
}
int dealCommand(int sockfd, const char *username, 
                const char *passwd, const char *tokenn, 
                const char *ip, const char *port){
    signal(SIGPIPE, handler);
    // 备份token
    char token[41] = {0};
    memcpy(token, tokenn, sizeof(token));

    // 定义TLV结构体
    tlvPacket_t tlv;
    memset(&tlv, 0, sizeof(tlv));

    // 初始化聊天头
    char cHeadName[4096] = {0};
    strcpy(cHeadName, username);
    static char cHead[4096] = {0};
    // 第一次加/， 后面传的都有/了
    if(strlen(cHead) == 0){
        cHead[0] = '/';
    }
    strcat(cHeadName, cHead);

    printf("> %s: ", cHeadName);
    fflush(stdout);

    char buffer[4096] = {0};
    char command[4096] = {0};
    char parameter[4096] = {0};
    char strtokBuffer[4096] = {0};

    // 获取stdin命令和参数
    fgets(buffer, sizeof(buffer), stdin);

    // 去除最后一个换行符
    if(buffer[strlen(buffer)-1] == '\n'){
        buffer[strlen(buffer)-1] = 0;
    }

    // 复制客户端输入
    memcpy(strtokBuffer, buffer, sizeof(buffer));
    const char delimiters[] = " "; // 截断依据

    // 截取命令
    char *mtoken = strtok(strtokBuffer, delimiters);
    memcpy(command, mtoken, strlen(token));
    //printf("command = %s\n", command);
    // 截取参数
    mtoken = strtok(NULL, delimiters);
    //printf("mtoken = %s\n", mtoken);
    if(mtoken != NULL){
        memcpy(parameter, mtoken, strlen(token));
    }
    //printf("-2\n");

    char content[4096] = {0}; // 接收内容
    int mark = 0; // 接受标志
                  //printf("-1\n");
                  // 日志记录
    LOG(username, command);

    // 触发SIGPIPE之前，初始化signalElement
    memset(&signalElement, 0, sizeof(signalElement));
    memcpy(signalElement.username, username, strlen(username));
    memcpy(signalElement.token, token, strlen(token));
    memcpy(signalElement.ip, ip, strlen(ip));
    memcpy(signalElement.port, port, strlen(port));

    reSockfd = sockfd;

    //printf("0\n");
    if(strcmp(command, "cd") == 0){
        // 如果cd后没有参数
        if(strlen(parameter) == 0){
            printf("Invalid command: cd!\n");
            return -1;
        }

        //printf("1\n");

        // 发送命令+参数
        tlv.type = CD;
        tlv.length = strlen(parameter);
        memcpy(tlv.value, parameter, tlv.length);
        // 初始化命令给信号用
        memcpy(&signalElement.tlv, &tlv, sizeof(tlv));
        send(sockfd, &tlv, sizeof(tlv.type)+sizeof(tlv.length)+
             tlv.length, 0);

        sockfd = reSockfd;

        //printf("2\n");

        // 发送用户名
        tlv.length = strlen(username);
        memcpy(tlv.value, username, tlv.length);
        send(sockfd, &tlv, sizeof(tlv.type)+sizeof(tlv.length)+
             tlv.length, MSG_NOSIGNAL);

        //printf("3\n");

        // 发送cHead(虚拟路径)
        tlv.length = strlen(cHead);
        memcpy(tlv.value, cHead, tlv.length);
        send(sockfd, &tlv, sizeof(tlv.type)+sizeof(tlv.length)+
             tlv.length, MSG_NOSIGNAL);

        //printf("4\n");

        // 发送token
        send(sockfd, token, sizeof(token), MSG_NOSIGNAL);

        //printf("5\n");

        // 接受标志
        recv(sockfd, &mark, sizeof(int), MSG_WAITALL);
        if(mark == -1){
            printf("cd false!\n");
            return -1;
        }

        //printf("6\n");

        // 接收路径
        recv(sockfd, &tlv.type, sizeof(commandType_t), MSG_WAITALL);
        recv(sockfd, &tlv.length, sizeof(int), MSG_WAITALL);
        recv(sockfd, tlv.value, tlv.length, MSG_WAITALL);
        memset(cHead, 0, sizeof(cHead));
        memcpy(cHead, tlv.value, tlv.length);

        //printf("7\n");
    }
    else if(strcmp(command, "ls") == 0){

        // 发送命令
        tlv.type = LS;
        tlv.length = strlen(parameter);
        // 初始化命令给信号用
        memcpy(&signalElement.tlv, &tlv, sizeof(tlv));
        send(sockfd, &tlv, sizeof(tlv.type)+sizeof(tlv.length)+
             tlv.length, 0);

        sockfd = reSockfd;


        // 发送用户名
        tlv.length = strlen(username);
        memcpy(tlv.value, username, tlv.length);
        send(sockfd, &tlv, sizeof(tlv.type)+sizeof(tlv.length)+
             tlv.length, MSG_NOSIGNAL);

        // 发送cHead(虚拟路径)
        tlv.length = strlen(cHead);
        memcpy(tlv.value, cHead, tlv.length);
        send(sockfd, &tlv, sizeof(tlv.type)+sizeof(tlv.length)+
             tlv.length, MSG_NOSIGNAL);

        // 发送token
        send(sockfd, token, sizeof(token), MSG_NOSIGNAL);

        // 接受标志
        recv(sockfd, &mark, sizeof(int), MSG_WAITALL);
        if(mark == -1){
            printf("ls false!\n");
            return -1;
        }

        // 接受内容
        recv(sockfd, &tlv.type, sizeof(commandType_t), MSG_WAITALL);
        recv(sockfd, &tlv.length, sizeof(int), MSG_WAITALL);
        //printf("length pass\n");
        if(tlv.length == 0){
            return 0;
        }
        recv(sockfd, tlv.value, tlv.length, MSG_WAITALL);
        //printf("value pass\n");
        memcpy(content, tlv.value, tlv.length);
        //printf("memcpy pass\n");

        printf("%s\n", content);

    }

    else if(strcmp(command, "tree") == 0){

        // 发送命令
        tlv.type = TREE;
        tlv.length = strlen(parameter);
        // 初始化命令给信号用
        memcpy(&signalElement.tlv, &tlv, sizeof(tlv));
        send(sockfd, &tlv, sizeof(tlv.type)+sizeof(tlv.length)+
             tlv.length, 0);

        sockfd = reSockfd;


        // 发送用户名
        tlv.length = strlen(username);
        memcpy(tlv.value, username, tlv.length);
        send(sockfd, &tlv, sizeof(tlv.type)+sizeof(tlv.length)+
             tlv.length, MSG_NOSIGNAL);

        // 发送cHead(虚拟路径)
        tlv.length = strlen(cHead);
        memcpy(tlv.value, cHead, tlv.length);
        send(sockfd, &tlv, sizeof(tlv.type)+sizeof(tlv.length)+
             tlv.length, MSG_NOSIGNAL);

        // 发送token
        send(sockfd, token, sizeof(token), MSG_NOSIGNAL);

        // 接受标志
        recv(sockfd, &mark, sizeof(int), MSG_WAITALL);
        if(mark == -1){
            printf("tree false!\n");
            return -1;
        }

        // 接受内容
        recv(sockfd, &tlv.type, sizeof(commandType_t), MSG_WAITALL);
        recv(sockfd, &tlv.length, sizeof(int), MSG_WAITALL);
        //printf("length pass\n");
        if(tlv.length == 0){
            return 0;
        }
        recv(sockfd, tlv.value, tlv.length, MSG_WAITALL);
        //printf("value pass\n");
        memcpy(content, tlv.value, tlv.length);
        //printf("memcpy pass\n");

        printf("%s\n", content);

    }

    else if(strcmp(command, "pwd") == 0){
        printf("%s\n", cHeadName);
    }

    else if(strcmp(command, "mkdir") == 0){

        // 如果mkdir后没有参数
        if(strlen(parameter) == 0){
            printf("Invalid command: mkdir!\n");
            return -1;
        }

        // 发送命令
        tlv.type = MKDIR;
        tlv.length = strlen(parameter);
        memcpy(tlv.value, parameter, tlv.length);
        // 初始化命令给信号用
        memcpy(&signalElement.tlv, &tlv, sizeof(tlv));
        send(sockfd, &tlv, sizeof(tlv.type)+sizeof(tlv.length)+
             tlv.length, 0);

        sockfd = reSockfd;

        // 发送用户名
        tlv.length = strlen(username);
        memcpy(tlv.value, username, tlv.length);
        send(sockfd, &tlv, sizeof(tlv.type)+sizeof(tlv.length)+
             tlv.length, MSG_NOSIGNAL);

        // 发送cHead(虚拟路径)
        tlv.length = strlen(cHead);
        memcpy(tlv.value, cHead, tlv.length);
        send(sockfd, &tlv, sizeof(tlv.type)+sizeof(tlv.length)+
             tlv.length, MSG_NOSIGNAL);

        // 发送token
        send(sockfd, token, sizeof(token), MSG_NOSIGNAL);

        // 接受标志
        recv(sockfd, &mark, sizeof(int), MSG_WAITALL);
        if(mark == -1){
            printf("mkdir false\n");
            return -1;
        }
    }

    else if(strcmp(command, "rmdir") == 0){

        // 如果rmdir后没有参数
        if(strlen(parameter) == 0){
            printf("Invalid command: rmdir!\n");
            return -1;
        }

        // 发送命令
        tlv.type = RMDIR;
        tlv.length = strlen(parameter);
        memcpy(tlv.value, parameter, tlv.length);
        // 初始化命令给信号用
        memcpy(&signalElement.tlv, &tlv, sizeof(tlv));
        send(sockfd, &tlv, sizeof(tlv.type)+sizeof(tlv.length)+
             tlv.length, 0);
        
        sockfd = reSockfd;

        // 发送用户名
        tlv.length = strlen(username);
        memcpy(tlv.value, username, tlv.length);
        send(sockfd, &tlv, sizeof(tlv.type)+sizeof(tlv.length)+
             tlv.length, MSG_NOSIGNAL);

        // 发送cHead(虚拟路径)
        tlv.length = strlen(cHead);
        memcpy(tlv.value, cHead, tlv.length);
        send(sockfd, &tlv, sizeof(tlv.type)+sizeof(tlv.length)+
             tlv.length, MSG_NOSIGNAL);

        // 发送token
        send(sockfd, token, sizeof(token), MSG_NOSIGNAL);
        // 接受标志
        recv(sockfd, &mark, sizeof(int), MSG_WAITALL);
        if(mark == -1){
            printf("rmdir false\n");
            return -1;
        }
    }

    else if(strcmp(command, "remove") == 0){

        // 如果remove后没有参数
        if(strlen(parameter) == 0){
            printf("Invalid command: remove!\n");
            return -1;
        }

        // 发送命令
        tlv.type = RM;
        tlv.length = strlen(parameter);
        memcpy(tlv.value, parameter, tlv.length);
        // 初始化命令给信号用
        memcpy(&signalElement.tlv, &tlv, sizeof(tlv));
        send(sockfd, &tlv, sizeof(tlv.type)+sizeof(tlv.length)+
             tlv.length, 0);
    
        sockfd = reSockfd;

        // 发送用户名
        tlv.length = strlen(username);
        memcpy(tlv.value, username, tlv.length);
        send(sockfd, &tlv, sizeof(tlv.type)+sizeof(tlv.length)+
             tlv.length, MSG_NOSIGNAL);

        // 发送cHead(虚拟路径)
        tlv.length = strlen(cHead);
        memcpy(tlv.value, cHead, tlv.length);
        send(sockfd, &tlv, sizeof(tlv.type)+sizeof(tlv.length)+
             tlv.length, MSG_NOSIGNAL);

        // 发送token
        send(sockfd, token, sizeof(token), MSG_NOSIGNAL);
        // 接受标志
        recv(sockfd, &mark, sizeof(int), MSG_WAITALL);
        if(mark == -1){
            printf("remove false\n");
            return -1;
        }
    }

    else if(strcmp(command, "puts") == 0){

        // 如果puts后没有参数
        if(strlen(parameter) == 0){
            printf("Invalid command: puts!\n");
            return -1;
        }

        // 初始化element结构体
        element_t element;
        memset(&element, 0, sizeof(element));
        element.tlv.type = PUTS;
        element.tlv.length = strlen(parameter);
        memcpy(element.tlv.value, parameter, element.tlv.length);
        memcpy(element.username, username, strlen(username));
        memcpy(element.cHead, cHead, strlen(cHead));
        memcpy(element.token, token, strlen(token));
        memcpy(element.ip, ip, strlen(ip));
        memcpy(element.port, port, strlen(port));

        // 创建子线程
        pthread_t pid;
        pthread_create(&pid, NULL, threadFunc, &element);
        pthread_join(pid, NULL);
    }

    else if(strcmp(command, "gets") == 0){

        // 如果gets后没有参数
        if(strlen(parameter) == 0){
            printf("Invalid command: gets!\n");
            return -1;
        }

        // 初始化element结构体
        element_t element;
        memset(&element, 0, sizeof(element));
        element.tlv.type = GETS;
        element.tlv.length = strlen(parameter);
        memcpy(element.tlv.value, parameter, element.tlv.length);
        memcpy(element.username, username, strlen(username));
        memcpy(element.cHead, cHead, strlen(cHead));
        memcpy(element.token, token, strlen(token));
        memcpy(element.ip, ip, strlen(ip));
        memcpy(element.port, port, strlen(port));

        // 创建子线程
        pthread_t pid;
        pthread_create(&pid, NULL, threadFunc, &element);
        pthread_join(pid, NULL);
    }

    else if(strcmp(command, "logout") == 0){

        close(sockfd);
        exit(-1);

    }

    else if(strcmp(command, "logoff") == 0){

        // 验证密码
        char *tmp = getPassword("请输入密码：");
        if(strcmp(tmp, passwd) == 0){

            // 发送命令
            tlv.type = ACCOUNTDELETE;
            tlv.length = strlen(parameter);
            // 初始化命令给信号用
            memcpy(&signalElement.tlv, &tlv, sizeof(tlv));
            send(sockfd, &tlv, sizeof(tlv.type)+sizeof(tlv.length)+
                 tlv.length, 0);
            
            sockfd = reSockfd;

            // 发送用户名
            tlv.length = strlen(username);
            memcpy(tlv.value, username, tlv.length);
            send(sockfd, &tlv, sizeof(tlv.type)+sizeof(tlv.length)+
                 tlv.length, MSG_NOSIGNAL);

            // 发送cHead(虚拟路径)
            tlv.length = strlen(cHead);
            memcpy(tlv.value, cHead, tlv.length);
            send(sockfd, &tlv, sizeof(tlv.type)+sizeof(tlv.length)+
                 tlv.length, MSG_NOSIGNAL);

            // 发送token
            send(sockfd, token, sizeof(token), MSG_NOSIGNAL);
            // 接受标志
            recv(sockfd, &mark, sizeof(int), MSG_WAITALL);
            if(mark == -1){
                printf("logoff false!\n");
                free(tmp); // 释放堆空间
                return -1;
            }
            printf("用户已删除！\n");
            exit(0);
        }
        else{
            printf("密码错误！\n");
        }
        free(tmp); // 释放堆空间

    }
    else{
        printf("command is not existence!\n");
        return -1;
    }

    return 0;
}
